package com.example.discover.repository

import android.util.Log
import androidx.annotation.WorkerThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData
import com.example.featuresdk.model.Book
import com.example.featuresdk.dao.BookDao
import com.example.featuresdk.repository.ReadAsFlow
import com.example.featuresdk.repository.ReadAsLiveData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

/*
 * The data and business layer should expose suspend functions and Flows
 * https://developer.android.google.cn/kotlin/coroutines/coroutines-best-practices#coroutines-data-layer
 *
 * Classes in the data and business layers generally expose functions to perform one-shot calls
 * or to be notified of data changes over time.
 *
 * Classes in those layers should expose suspend functions for one-shot calls and Flow to notify about data changes.
 */
@WorkerThread
class BookRepository @Inject constructor(private val bookDao: BookDao, private val bookWebService: BookWebService){

    suspend fun getAll(scope: CoroutineScope): LiveData<List<Book>> {
        return ReadAsLiveData(
            fetchLocalData = { bookDao.getAll().asLiveData() },
            shouldFetchRemoteData = { localData -> localData.isNullOrEmpty() },
            fetchRemoteData = { bookWebService.getBooks() },
            onStatusChanged = {Log.i("","***Status=${it}")},
            saveRemoteData = { remoteData -> bookDao.insert(remoteData) }
        ).execute(scope)
    }

    suspend fun getAll(): Flow<List<Book>> {
        return ReadAsFlow(
            fetchLocalData = { bookDao.getAll() },
            shouldFetchRemoteData = { true },
            fetchRemoteData = { bookWebService.getBooks() },
            saveRemoteData = { remoteData -> bookDao.insert(remoteData) }
        ).execute()
    }

    fun bookCount() : Flow<Int> = bookDao.getCount()

    fun get(isbn: String): Flow<Book>? {
        return bookDao.get(isbn)
    }

    suspend fun insert(vararg books: Book) {
        //TODO: Update remote repository using bookWebService
        bookDao.insert(*books)
    }

    suspend fun insert(books: List<Book>) {
        //TODO: Update remote repository using bookWebService
        bookDao.insert(books)
    }

    suspend fun delete(isbn: String){

        //bookWebService.deleteBook(isbn)

        Log.i("BookRepository", "Delete book $isbn")

        bookDao.delete(isbn)
    }

    suspend fun deleteAll(){
        //TODO: Update remote repository using bookWebService
        bookDao.deleteAll()
    }

    suspend fun update(isbn: String,price: String){
        //TODO: Update remote repository using bookWebService
        bookDao.update(BookDao.Price(isbn,price))
    }

    suspend fun update(book: Book){
        //TODO: Update remote repository using bookWebService
        bookDao.update(book)
    }
}